package com.slashvision.stylist.im

import android.media.MediaPlayer
import android.media.MediaRecorder
import android.os.Build
import com.slashvision.im.ContextUtil
import com.slashvision.im.SLog
import com.slashvision.im.TAG
import com.slashvision.im.toastShort
import com.slashvision.im.tool.StorgeUtil
import io.openim.android.sdk.enums.MessageType
import io.openim.android.sdk.models.Message
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.*
import java.nio.file.Files.exists

/**
 * author : lizhenxin
 *  date  : 2021/10/14
 *  desc  :
 */
/**
 * @desc:
 * @author: LiZhenxin
 * @create:
 * update
 **/
const val TAG_IM_VOICE = "_TAG_IM_VOICE_"
object RecordVoiceUtil {


    private var mCurrentTimeStamp: Long = 0L

    private var mediaRecorder: MediaRecorder? = null

    private val mPlayer: MediaPlayer = MediaPlayer().apply {
        this.setOnPreparedListener(mOnPreparedListener)
    }

    private val mOnPreparedListener = MediaPlayer.OnPreparedListener { it.start() }


    suspend fun startRecord() = withContext(Dispatchers.IO) {
        mCurrentTimeStamp = System.currentTimeMillis()
        mediaRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            MediaRecorder(ContextUtil.getContext())
        } else {
            MediaRecorder()
        }.apply {
            setAudioSource(MediaRecorder.AudioSource.MIC)
            setOutputFormat(MediaRecorder.OutputFormat.DEFAULT)
            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
            setMaxDuration(60 * 1000)

            val f = File(getCurrentFile().absolutePath)
            if (!f.exists()) {
                f.createNewFile()
            }
            setOutputFile(f.absolutePath)
            prepare()
            start()
        }
    }

    suspend fun stopRecord(): VoiceFileInfo = withContext(Dispatchers.IO) {
        val duration = System.currentTimeMillis() - mCurrentTimeStamp
        SLog.d(TAG_IM_VOICE, "录音时长：${duration}")
        mediaRecorder?.apply {
            stop()
            release()
        }
        VoiceFileInfo(
            path = getCurrentFile().absolutePath,
            duration = duration
        )
    }

    suspend fun cancelRecord() {
        stopRecord()
        getCurrentFile().takeIf { it.exists() }?.delete()
    }


    fun isPlaying() = mPlayer.isPlaying ?: false
    suspend fun startPlayRecord(absPath: String, onComplete: () -> Unit) =
        withContext(Dispatchers.IO) {
            File(absPath).takeIf { it.exists() }?.let {
                SLog.f(this@RecordVoiceUtil.TAG())
                mPlayer?.takeIf { !it.isPlaying }?.apply {
                    setOnCompletionListener {
                        onComplete()
                    }
                    SLog.d(TAG_IM_VOICE, "-------------$absPath")
                    reset()
                    setDataSource(absPath)
                    prepare()
                } ?: stopPlayRecord()
            }
        }

    suspend fun startPlayRecord(file: File, onComplete: () -> Unit) = withContext(Dispatchers.IO) {
        file.takeIf { it.exists() }?.let {
            SLog.f(this@RecordVoiceUtil.TAG())
            mPlayer?.takeIf { !it.isPlaying }?.apply {
                reset()
                setOnCompletionListener {
                    onComplete()
                }
                setDataSource(file.absolutePath)
                prepare()
            } ?: stopPlayRecord()
        }

    }

    suspend fun startPlayRecord(msg: Message, onComplete: () -> Unit) = withContext(Dispatchers.IO) {
        check(msg.contentType == MessageType.VOICE)
        File(msg.soundElem.soundPath).takeUnless { it.exists() }?.let {
            downloadVoiceFile(msg.soundElem.sourceUrl, msg.soundElem.soundPath, onComplete = {
                this.launch {
                    startPlayRecord(msg.soundElem.soundPath, onComplete)
                }
            }, {
                ContextUtil.getContext().toastShort("下载语音文件出错，请重试")
            })
        } ?: startPlayRecord(msg.soundElem.soundPath, onComplete)
    }

    suspend fun stopPlayRecord() = withContext(Dispatchers.IO) {
        mPlayer?.takeIf { it.isPlaying }?.apply {
            SLog.f(this@RecordVoiceUtil.TAG())
            stop()
            reset()
        }
    }


    fun downloadVoiceFile(
        url: String,
        path: String,
        onComplete: (String) -> Unit,
        onError: (String) -> Unit
    ) {
//        IMRetrofit.downloadFile(url, path, onSuccess = onComplete, onError = onError)
    }

    fun getPlayerPosition() = mPlayer?.takeIf { it.isPlaying }?.currentPosition ?: -1

    private fun getCurrentFile() = File(StorgeUtil.voiceCacheDir, "${mCurrentTimeStamp}.amr")
}

data class VoiceFileInfo(
    val path: String,
    val duration: Long
)